package com.pipayshop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pipayshop.entity.*;
import com.pipayshop.entity.dto.HotelShopInfoListByConditionDTO;
import com.pipayshop.entity.vo.*;
import com.pipayshop.exception.BusinessException;
import com.pipayshop.mapper.*;
import com.pipayshop.service.HotelShopInfoService;
import com.pipayshop.utils.RedisUtil;
import com.pipayshop.utils.StringUtil;
import com.pipayshop.utils.ValidationUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.pipayshop.utils.Constants.HOTEL_INFO_LIST;
import static com.pipayshop.utils.Constants.HOTEL_ROOM_LIST;

/**
 * <p>
 * 实体店酒店的信息 服务实现类
 * </p>
 *
 * @author nws
 * @since 2023-07-25
 */
@Service
public class HotelShopInfoServiceImpl extends ServiceImpl<HotelShopInfoMapper, HotelShopInfo> implements HotelShopInfoService {

    @Resource
    private HotelShopInfoMapper shopInfoMapper;

    @Resource
    private HotelShopTagsMapper shopTagsMapper;

    @Resource
    private ImageMapper imageMapper;
    @Resource
    private HotelShopCommodityLiveInfoMapper shopCommodityLiveInfoMapper;
    @Resource
    private RedisUtil redisUtil;


    /**
     * 首页获取所有实体店列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageDataVO getShopInfoListByCondition(HotelShopInfoListByConditionDTO hotelShopInfoListByConditionDTO) {

        if (StringUtils.isBlank(hotelShopInfoListByConditionDTO.getRegionId())) {
            throw new BusinessException("region_id_required");
        }

        // 获取总条数
        Integer count = shopInfoMapper.getIndexShopInfoVOCount(hotelShopInfoListByConditionDTO.getCategoryId(), hotelShopInfoListByConditionDTO.getRegionId(), hotelShopInfoListByConditionDTO.getShopName());
        System.out.println(hotelShopInfoListByConditionDTO);
        List<IndexShopInfoVO> indexShopInfoVO = shopInfoMapper.getIndexShopInfoVO(hotelShopInfoListByConditionDTO.getCategoryId(),
                (hotelShopInfoListByConditionDTO.getPage() - 1) * hotelShopInfoListByConditionDTO.getLimit(),
                hotelShopInfoListByConditionDTO.getLimit(),
                hotelShopInfoListByConditionDTO.getScore(),
                hotelShopInfoListByConditionDTO.getRegionId(),
                hotelShopInfoListByConditionDTO.getShopName(),
                hotelShopInfoListByConditionDTO.getLatitude(),
                hotelShopInfoListByConditionDTO.getLongitude());
        indexShopInfoVO
                .stream()
                .parallel()
                .forEach(shopInfoVO -> {
                    List<String> list1 = new ArrayList<>();
                    List<String> list = JSON.parseArray(shopInfoVO.getTagList(), String.class);
                    if (list == null || list.isEmpty()) {
                        return;
                    }
                    for (String tagId : list) {
                        String tagContent = shopTagsMapper.selectOneContent(tagId);
                        list1.add(tagContent);
                    }
                    shopInfoVO.setShopTagsList(list1);
                });
        return new PageDataVO(count, indexShopInfoVO);
    }


    /**
     * 根据条件查询酒店信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageDataVO getHotelInfoByCondition(LivePageVO livePageVO) {
        if (StringUtils.isBlank(livePageVO.getRegionId())) {
            throw new BusinessException("region_id_required");
        }
        if (StringUtils.isBlank(livePageVO.getShopName())) {
            throw new BusinessException("shop_name_required");
        }
        Integer limit = livePageVO.getLimit();
        Integer page = livePageVO.getPage();

        List<IndexShopInfoVO> indexShopInfoVOS = shopInfoMapper.getHotelInfoByCondition(
                livePageVO.getShopName(),
                limit,
                (page - 1) * limit,
                livePageVO.getCheckInTime(),
                livePageVO.getDepartureTime(),
                livePageVO.getAdult(),
                livePageVO.getChildren(),
                livePageVO.getRegionId());
        for (IndexShopInfoVO indexShopInfoVO : indexShopInfoVOS) {
            indexShopInfoVO.setUserImage(imageMapper.selectPath(indexShopInfoVO.getUserImage()));
        }
        for (IndexShopInfoVO shopInfoVO : indexShopInfoVOS) {
            List<String> list1 = new ArrayList<>();
            List<String> list = JSON.parseArray(shopInfoVO.getTagList(), String.class);
            if (list == null || list.isEmpty()) {
                continue;
            }
            for (String s : list) {
                String tagId = shopTagsMapper.selectOneContent(s);
                list1.add(tagId);
            }

            shopInfoVO.setShopTagsList(list1);
        }

        Integer num = shopInfoMapper.getHotelInfoNum(
                livePageVO.getShopName(),
                livePageVO.getCheckInTime(),
                livePageVO.getDepartureTime(),
                livePageVO.getAdult(),
                livePageVO.getChildren(), livePageVO.getRegionId());
        return new PageDataVO(num, indexShopInfoVOS);
    }

    // 批量查询酒店数量
    public Map<String, Long> getHotelCountsByRegionIds(List<String> regionIds) {
        Map<String, Long> result = new HashMap<>();
        for (String regionId : regionIds) {
            String categoryId = "fwefw"; // 这里可以动态调整
            long count = shopInfoMapper.countHotelsByRegionPrefix(categoryId, regionId);
            result.put(regionId, count);
        }
        return result;
    }

    /**
     * 根据实体店id查询实体店信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ShopInfoVO getShopInfoById(String shopId) {
        ShopInfoVO shopInfoVO = new ShopInfoVO();
        HotelShopInfo hotelShopInfo = shopInfoMapper.selectOne(new QueryWrapper<HotelShopInfo>()
                .eq("status", 0)
                .eq("shop_id", shopId));

        BeanUtils.copyProperties(hotelShopInfo, shopInfoVO);
        // 解析imageList数据
        List<String> imageList = JSON.parseArray(hotelShopInfo.getShopImagList(), String.class);
        List<String> images = imageList.stream()
                .parallel()
                .map(imageId -> imageMapper.selectPath(imageId))
                .collect(Collectors.toList());
        // 解析userImage数据
        shopInfoVO.setShopImagList(images);
        shopInfoVO.setUserImage(imageMapper.selectPath(shopInfoVO.getUserImage()));
        return shopInfoVO;

    }

    @Override
    public HotelShopInfoVO getShopInfoByUid(String uid) {
        // 读取缓存
        Object cacheObject = redisUtil.getCacheObject(HOTEL_INFO_LIST+uid);
        // 转换成对象
        if (cacheObject != null) {
            return BeanUtil.copyProperties(cacheObject, HotelShopInfoVO.class);
        }
        HotelShopInfoVO shopInfoVO = new HotelShopInfoVO();
        HotelShopInfo hotelShopInfo = shopInfoMapper.selectOne(new QueryWrapper<HotelShopInfo>()
                .eq("status", 0)
                .eq("category_id", "fwefw")
                .eq("uid", uid));

        // 如果没有找到商店信息，则直接返回空数据
        if (hotelShopInfo == null) {
            return shopInfoVO;
        }

        BeanUtils.copyProperties(hotelShopInfo, shopInfoVO);
        // 解析imageList数据

        List<String> imageListId =
                hotelShopInfo.getShopImagList() != null ?
                        JSON.parseArray(hotelShopInfo.getShopImagList(), String.class)
                        :
                        Collections.emptyList();

        String userImageId = hotelShopInfo.getUserImage();
        String qrcodeImageId = hotelShopInfo.getQrcode();
        List<String> images = imageListId.stream()
                .parallel()
                .map(imageId -> imageMapper.selectPath(imageId))
                .collect(Collectors.toList());

        // 查询 userImage 和 qrcodeImage 的路径，若为空则返回空字符串或默认值
        String userImage = (userImageId != null) ? imageMapper.selectPath(userImageId) : "";
        String qrcodeImage = (qrcodeImageId != null) ? imageMapper.selectPath(qrcodeImageId) : "";

        // 构建 imageMap，使用 safeMap 方法来处理 null 或空值
        Map<String, String> imageMap = buildImageMap(imageListId, images);
        Map<String, String> userImageMap = buildImageMap(Collections.singletonList(userImageId), Collections.singletonList(userImage));
        Map<String, String> qrcodeImageMap = buildImageMap(Collections.singletonList(qrcodeImageId), Collections.singletonList(qrcodeImage));

        // 设置到 VO 中
        if (imageListId != null && !imageListId.isEmpty()) {
            shopInfoVO.setShopImagList(imageMap);
        }
        if (userImageId != null) {
            shopInfoVO.setUserImage(userImageMap);
        }
        if (qrcodeImageId != null) {
            shopInfoVO.setQrcode(qrcodeImageMap);
        }

        // 存入redis缓存
        redisUtil.setCacheObject(HOTEL_INFO_LIST+uid, shopInfoVO,10, TimeUnit.DAYS);
        return shopInfoVO;
    }

    // 创建通用方法来构建 Map
    private Map<String, String> buildImageMap(List<String> imageIds, List<String> imagePaths) {
        // 如果 imageIds 或 imagePaths 为 null 或其长度不一致，返回空 Map
        if (imageIds == null || imagePaths == null || imageIds.size() != imagePaths.size()) {
            return Collections.emptyMap();
        }

        Map<String, String> imageMap = new HashMap<>();
        for (int i = 0; i < imageIds.size(); i++) {
            imageMap.put(imageIds.get(i), imagePaths.get(i));
        }
        return imageMap;
    }

    @Override
    public boolean updateHotel(ShopInfoVO shopInfoVO) {
        // 判断酒店名称是否已经存在
        if (shopInfoMapper.selectCount(new LambdaQueryWrapper<HotelShopInfo>()
                .eq(HotelShopInfo::getShopName, shopInfoVO.getShopName())
                .ne(HotelShopInfo::getShopId, shopInfoVO.getShopId())) > 0) {
            return false;
        }
        // 校验必要字段
        ValidationUtil.validateString(shopInfoVO.getShopId(), "shop_id_required");

        ValidationUtil.validateString(shopInfoVO.getShopName(), "shop_name_required");

        ValidationUtil.validateString(shopInfoVO.getPhone(), "contact_phone_required");


        // 如果所有校验通过，执行更新操作
        HotelShopInfo hotelShopInfo = BeanUtil.copyProperties(shopInfoVO, HotelShopInfo.class);
        hotelShopInfo.setShopImagList(JSON.toJSONString(shopInfoVO.getShopImagList()));
        int update = shopInfoMapper.update(hotelShopInfo, new LambdaUpdateWrapper<HotelShopInfo>()
                .eq(HotelShopInfo::getShopId, hotelShopInfo.getShopId()));
        if (update >0){
            redisUtil.deleteObject(HOTEL_INFO_LIST+shopInfoVO.getUid());
        }
        return update > 0;
    }




    @Override
    public List<RoomListVO> getShopInfoByShopId(String shopId) {
        // 读取缓存
        Object cacheObject = redisUtil.getCacheObject(HOTEL_ROOM_LIST + shopId);
        // 转换成对象
        if (cacheObject != null) {
            ObjectMapper objectMapper = new ObjectMapper();

            // cacheObject  JSON 数组，可以转换为数组
            List<RoomListVO> roomList = objectMapper.convertValue(cacheObject, new TypeReference<List<RoomListVO>>(){});

            return roomList;
        }
        // 查询数据
        List<ShopCommodityLiveInfo> shopCommodityLiveInfos = shopCommodityLiveInfoMapper.selectList(new LambdaQueryWrapper<ShopCommodityLiveInfo>()
                .eq(ShopCommodityLiveInfo::getShopId, shopId));

        // 如果没有数据，直接返回空
        if (shopCommodityLiveInfos == null || shopCommodityLiveInfos.isEmpty()) {
            return Collections.emptyList();
        }

        List<RoomListVO> roomListVOS = new ArrayList<>();
        for (ShopCommodityLiveInfo shopCommodityLiveInfo : shopCommodityLiveInfos) {
            RoomListVO roomListVO = new RoomListVO();
            String basics = shopCommodityLiveInfo.getBasics();
            String bath = shopCommodityLiveInfo.getBath();
            String appliance = shopCommodityLiveInfo.getAppliance();
            String imageList = shopCommodityLiveInfo.getImageList();
            String tagList = shopCommodityLiveInfo.getTagList();
            // 解析设施成数组
            List<HotelFacilityVO> basicsHotelFacilityVOS = JSON.parseArray(basics, HotelFacilityVO.class);
            List<HotelFacilityVO> bathHotelFacilityVOS = JSON.parseArray(bath, HotelFacilityVO.class);
            List<HotelFacilityVO> applianceHotelFacilityVOS = JSON.parseArray(appliance, HotelFacilityVO.class);
//            // 解析imageList
            List<String> imageListList = JSON.parseArray(imageList, String.class);
//            // 解析tagList
            List<String> tagListList = JSON.parseArray(tagList, String.class);
            roomListVO.setImageList(imageListList);
            roomListVO.setTagList(tagListList);
            roomListVO.setAdult(shopCommodityLiveInfo.getAdult());
            roomListVO.setChildren(shopCommodityLiveInfo.getChildren());
            roomListVO.setRestRoom(shopCommodityLiveInfo.getRestRoom());
            roomListVO.setBed(shopCommodityLiveInfo.getBed());
            roomListVO.setLand(shopCommodityLiveInfo.getLand());
            roomListVO.setRoom(shopCommodityLiveInfo.getRoom());
            roomListVO.setRoomId(shopCommodityLiveInfo.getRoomId());
            roomListVO.setRoomTypeName(shopCommodityLiveInfo.getRoomTypeName());
            roomListVO.setInventory(shopCommodityLiveInfo.getInventory());
            roomListVO.setDetail(shopCommodityLiveInfo.getDetail());
            roomListVO.setPrice(shopCommodityLiveInfo.getPrice());
            roomListVO.setRestricted(shopCommodityLiveInfo.getRestricted());
            roomListVO.setAvatarImag(shopCommodityLiveInfo.getAvatarImag());
            roomListVO.setBedType(shopCommodityLiveInfo.getBedType());
            roomListVO.setFloor(shopCommodityLiveInfo.getFloor());
            roomListVO.setIsAdd(shopCommodityLiveInfo.getIsAdd());
            roomListVO.setMonthlySales(shopCommodityLiveInfo.getMonthlySales());
            roomListVO.setPiFlag(shopCommodityLiveInfo.getPiFlag());
            roomListVO.setBasics(basicsHotelFacilityVOS);
            roomListVO.setBath(bathHotelFacilityVOS);
            roomListVO.setAppliance(applianceHotelFacilityVOS);
            roomListVO.setRecommended(shopCommodityLiveInfo.getRecommended());
            roomListVO.setStatus(shopCommodityLiveInfo.getStatus());
            // 解析获取图片url
            roomListVO.setImageListURL(imageListList.stream()
                    .map(imageMapper::selectPath)
                    .collect(Collectors.toList()));
            roomListVOS.add(roomListVO);
        }
        // 存入缓存
        redisUtil.setCacheObject(HOTEL_ROOM_LIST + shopId, roomListVOS,10, TimeUnit.DAYS);
        return roomListVOS;
    }


    @Override
    public boolean takeOffRoom(String roomId,String hotelId) {
        int update = shopCommodityLiveInfoMapper.takeOffRoom(roomId);
        if (update > 0) {
            // 删除缓存
            redisUtil.deleteObject(HOTEL_ROOM_LIST + hotelId);
        }
        return update >= 1 ? true : false;
    }
}
